"""
查询程序的接口模块，定义了基本类和类方法
"""
from base64 import b64decode, b64encode
from pathlib import Path
from random import randint

import json


def get_base64(s: str, salt: int = 20) -> str:
    """
    文本加密函数，主要用于账号密码的加密
    :param s: 需要加密字符串
    :param salt: salt长度
    :return:
    """
    salt = ''.join([chr(randint(48, 122)) for i in range(salt)])
    return b64encode((s + salt).encode('utf-8')).decode('utf-8')


class User:
    """
    用户类，基本类，无类方法
    """
    def __init__(self, username, password, role):
        """
        self.role 用户权限：1为学生，2为教师
        self.locked 用户锁定开关
        """
        self.username = username
        self.password = password
        self.role = role
        self.locked = False


class Result:
    """
    考试成绩类，基本类，无类方法
    """
    def __init__(self, name, chinese, math, english):
        self.name = name
        self.chinese = chinese
        self.math = math
        self.english = english


class Query:
    """
    查询类，本程序的主接口类
    """
    def __init__(self):
        self.user = None
        # self.query = {} TODO
        # self.record = {} TODO

    def __get_str(self, s: str, salt: int = 20) -> str:
        """
        文本解密函数
        :param s: 需要解密字符串
        :param salt: salt长度
        :return:
        """
        return (b64decode(s)[:-salt]).decode('utf-8')

    @classmethod
    def load_file(cls, file: str):
        """
        类方法，生成器函数，读取文件
        :param file: 文件路径字符串
        :return: 返回一个生成器
        """
        p = Path(file)
        try:
            with p.open('r', encoding='utf-8') as f:
                yield from (json.loads(line) for line in f if line.strip())
        except StopIteration:
            return "Data is not exist."
        except FileNotFoundError:
            return "File Not Found Error"

    def write_file(self, file: str, s: dict):
        """
        写文件对象方法
        :param file: 文件路径
        :param s: 用户成绩
        :return:
        """
        p = Path(file)
        try:
            with p.open('a', encoding='utf-8') as f:
                f.write('\n')
                json.dump(s, f)
        except FileNotFoundError:
            return "File Not Found Error"


    def record_scores(self, name: str):
        """
        登记成绩对象方法
        :param name: 学生姓名
        :return: 成绩对象
        """
        scores = input("请输入语文、数学、英语成绩，用空格分开：")
        scores = scores.split()
        if len(scores) != 3:
            print("输入成绩的科目必须等于3项！")
            raise ValueError
        for i in range(len(scores)):
            try:
                scores[i] = int(scores[i])
            except ValueError:
                print("输入的成绩有非数字字符！")
                raise
            if scores[i] < 0 or scores[i] > 100:
                print("输入的成绩必须在0-100！")
                raise ValueError
        return Result(name, *scores)

    def login(self, accounts):
        """
        对象登陆方法
        :return:
        """
        while True:
            username = input("请输入用户名:(退出请输入q)")
            if username == 'q':
                print("程序退出!")
                return
            elif username not in accounts:
                print("该用户不存在!")
                continue
            elif accounts[username].locked:
                print("该用户已被锁定,无法登陆.")
                continue
            else:
                count = 3
                while count:
                    password = input("请输入用户密码：")
                    if password != self.__get_str(accounts[username].password):
                        count -= 1
                        print("密码错误,还剩 {} 次机会。".format(count))
                        if count == 0:
                            accounts[username].locked = True
                            print("账户锁定!")
                            break
                    else:
                        self.user = accounts[username]
                        return self.user.role
